#pragma once

#include <string>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include <stdarg.h>
#include <stack>
#include <fstream>
#include <iostream>
#include <memory>

#include "pugixml/pugixml.hpp"

#include "topcvt_common.hpp"
#include "topcvt_logutil.hpp"
#include "topcvt_component.hpp"
#include "topcvt_exception.hpp"

using namespace std;
using namespace topcvt;

#define maxBuffSize 8192

static void  format_args(char* sbuf, const char* fmt, ...)
{
    char tbuf[maxBuffSize] = { 0 };
    va_list ap;
    va_start(ap, fmt);
    vsnprintf(tbuf, sizeof(tbuf), fmt, ap);
    va_end(ap);
    strcpy(sbuf, tbuf);
}

#define infoLog(fmt, ...) \
    {\
        char sbuf[maxBuffSize] = { 0 }; \
        format_args(sbuf,fmt,##__VA_ARGS__);\
        printf("%s\n", sbuf); \
        TLOG_INFO("%s",sbuf); \
    }

#define errorLog(fmt, ...) \
    {\
        char sbuf[maxBuffSize] = { 0 }; \
        format_args(sbuf,fmt,##__VA_ARGS__);\
        printf("%s\n", sbuf); \
        TLOG_INFO("%s",sbuf); \
    }

#define pexit_info(fmt, ...) \    
{\
    char sbuf[maxBuffSize] = { 0 }; \
    format_args(sbuf,fmt,##__VA_ARGS__);\
    printf("%s\n", sbuf); \
    exit_system(0);\
}

class CVTPkt_Parser
{
private:
	std::stack<Object> m_ctx;
	Object m_fmaps;
    vector<string> m_fields;
    map<string,vector<string>> m_maps_fields;
public:
	CVTPkt_Parser() = default;
	~CVTPkt_Parser() = default; 
	
	int CVTPkt_parser(const string& pktfile);
    int CVTPkt_parser(pugi::xml_node& xmlroot);
    Object& CVTPkt_getFields();
    vector<string> CVTPkt_getLoopFields();
    vector<string> CVTPkt_getLoopFields(const string& loopName);
private:    
	int CVTPkt_parser_node(pugi::xml_node& pktNode);
    int CVTPkt_parserStruct(pugi::xml_node& input);
    int CVTPkt_parserLoop(pugi::xml_node& input);
    int CVTPkt_parserInclude(pugi::xml_node& input);
    int CVTPkt_parserField(pugi::xml_node& input);
    int CVTPkt_parserDefault(pugi::xml_node& input);
};